package com.biao.transaction.example.common.util;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


/**
 * @description: 反向工程，将表结构转为对象，自动生成controller,service,entity,mapper等对象
 * @author:chenwenbiao
 * @createTime:2019/3/18 14:48
 * @version：1.0
 **/
public class GenerateControllerServiceMapperUtil {

    private static String configPath = "/src/main/resources/application.properties";
    private static String[] tableName = new String[]{"operate_a","operate_b"};

    /**
     * 作者
     */
    private static String author;

    /**
     * 数据库
     */
    private static String url;
    private static String driverName;
    private static String userName;
    private static String password;

    private static String projectPath;

    /**
     * 代码生成的目录
     */
    private static String packageName;
    private static String outputPath;
    private static String mapperXmlPath;
    private static String vuePath;

    public static void main(String[] args) {

        /**
         * 初始化变量
         */
        initial();

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();

        gc.setOutputDir(projectPath + outputPath);
        //如果文件存在是否覆盖，覆盖有风险，最好不要覆盖
        gc.setFileOverride(false);
        gc.setActiveRecord(true);
        // XML 二级缓存
        gc.setEnableCache(false);
        gc.setBaseResultMap(true);
        gc.setBaseColumnList(false);
        gc.setAuthor(author);
        gc.setOpen(false);

        //生成文件名:
        gc.setXmlName("%sMapper");
        gc.setMapperName("%sMapper");
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        gc.setControllerName("%sController");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(url);
        dsc.setDriverName(driverName);
        dsc.setUsername(userName);
        dsc.setPassword(password);
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent(packageName);
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 自定义controller的代码模板
        String templatePath = "/mybatis-plus-generator-template/controller.java.ftl";
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + outputPath + "/" + packageName.replace(".", "/") + "/controller";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getControllerName());
                return entityFile;
            }
        });




        // 自定义service的代码模板
        templatePath ="/mybatis-plus-generator-template/service.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + outputPath + "/" + packageName.replace(".", "/") + "/service";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getServiceName());
                return entityFile;
            }
        });

        // 自定义serviceImpl的代码模板
        templatePath ="/mybatis-plus-generator-template/serviceImpl.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + outputPath + "/" + packageName.replace(".", "/") + "/service/impl";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getServiceImplName());
                return entityFile;
            }
        });


        // 自定义mapper的代码模板
        templatePath ="/mybatis-plus-generator-template/mapper.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + outputPath + "/" + packageName.replace(".", "/") + "/mapper";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getMapperName());
                return entityFile;
            }
        });



        // 自定义mapper.xml的代码模板
        templatePath ="/mybatis-plus-generator-template/mapper.xml.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                return projectPath + mapperXmlPath + tableInfo.getEntityName() + "Mapper" +StringPool.DOT_XML;
            }
        });


/*
        // 自定义vue的代码模板
        templatePath = "/mybatis-plus-generator-template/vue.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                return projectPath + vuePath + StringUtils.firstCharToLower(tableInfo.getEntityName()) + ".vue";
            }
        });

        // 自定义vue api的代码模板
        templatePath ="/mybatis-plus-generator-template/apiService.js";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                return projectPath + vuePath + StringUtils.firstCharToLower(tableInfo.getEntityName()) + "ApiService.js";
            }
        });

        // 自定义vue service的代码模板
        templatePath ="/mybatis-plus-generator-template/urlConfig.js";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                return projectPath + vuePath + StringUtils.firstCharToLower(tableInfo.getEntityName()) + "UrlConfig.js";
            }
        });
*/

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        templateConfig.setXml(null);
        templateConfig.setController(null);
        mpg.setTemplate(templateConfig);



        // 策略配置
        StrategyConfig strategy = new StrategyConfig();

        /**
         *设置表名前缀；
         *此表名前缀若与数据库表名前缀一致，则自动创建实体类时，实体类名匹配数据库表名下划线后面的名；
         *栗子：数据库表名为 admin_info ，当strategy.setTablePrefix("admin_")时，则实体类名为Info；
         *若不设置表名前缀，则实体类名匹配数据库表名
         * b_开头的是表示基础表
         * bus_开头的表示业务表
         */
        strategy.setTablePrefix(new String[]{"c_", "t_", "bus_", "b_", "res_"});

        /**
         * 需要生成代码的表的设置
         * 若不设置则会生成全表的代码
         */
        strategy.setInclude(tableName);
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        //驼峰转连字符
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }


    public static void initial() {
        Properties prop = new Properties();
        try {

            projectPath = System.getProperty("user.dir");

            //读取属性文件a.properties
            InputStream in = new BufferedInputStream(new FileInputStream(projectPath + configPath));
            ///加载属性列表
            prop.load(in);
            in.close();

            author = prop.getProperty("code.generator-author");
            url = prop.getProperty("spring.datasource.url");
            driverName = prop.getProperty("spring.datasource.driverClassName");
            userName = prop.getProperty("spring.datasource.username");
            password = prop.getProperty("spring.datasource.password");
            outputPath = prop.getProperty("code.generator-output-path");
            packageName = prop.getProperty("code.generator-package-name");
            mapperXmlPath = prop.getProperty("code.generator-mapper-xml-path");
            vuePath = prop.getProperty("code.generator-vue-path");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



}